package com.ruoyi.partybuilding.controller;


import com.easy.query.api.proxy.util.EasyParamExpressionUtil;
import com.easy.query.core.configuration.EasyQueryOption;
import com.easy.query.core.util.EasyAesUtil;
import com.easy.query.core.util.EasyIncludeUtil;
import com.easy.query.sql.starter.config.EasyQueryProperties;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.PermissionService;
import com.ruoyi.partybuilding.common.*;
import com.ruoyi.partybuilding.common.EQuery.IEQueryEntity;
import com.ruoyi.partybuilding.domain.ReleaseDetails;
import com.ruoyi.partybuilding.domain.ReleaseTask;
import com.ruoyi.partybuilding.domain.vo.ReleaseTaskDto;
import com.ruoyi.partybuilding.domain.vo.ReleaseTaskVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.var;
import org.apache.commons.collections4.keyvalue.DefaultKeyValue;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "揭榜挂帅")
@RestController
@RequestMapping("/partybuilding/ReleaseTask")
public class ReleaseTaskController extends EQueryController<ReleaseTask> {


    @ApiOperation(value = "列表",notes = ConstData.ReleaseTask_StageVals)
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.list)")
    @GetMapping("/list")
    @DataScope
    public TableDataInfoRows<ReleaseTask> list(ReleaseTask entity, PageSort page) {
        var re = super.list(entity, page);
        return re;
    }
    @ApiOperation(value = "我创建的",notes = ConstData.ReleaseTask_StageVals)
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.myList)")
    @GetMapping("/myList")
    public TableDataInfoRows<ReleaseTask> myList(ReleaseTask entity, PageSort page) {
        entity.setCreateBy(getUsername());
        var re = super.list(entity, page);
        return re;
    }

    @ApiOperation(value = "查询阶段详情",notes = "用于展示阶段信息列表")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.list)")
    @GetMapping("/detailList")
    public TableDataInfoRows<ReleaseDetails> detailList(ReleaseDetails entity, PageSort page) {
        var query = queryHelper.queryable(ReleaseDetails.class).whereObject(entity)
                .groupBy(p -> p.column(ReleaseDetails::getReleaseTaskId).column(ReleaseDetails::getStage))
                .select(ReleaseDetails.class, r -> {
                    r.columnMax(ReleaseDetails::getId);
                    r.columnMax(ReleaseDetails::getTitle);
                    r.columnMax(ReleaseDetails::getContent);
                    r.columnMax(ReleaseDetails::getFiles);
                    r.columnMax(ReleaseDetails::getNikename);
                    r.columnMax(ReleaseDetails::getCreateBy);
                    r.columnMax(ReleaseDetails::getCreateTime);
                    r.column(ReleaseDetails::getReleaseTaskId);
                    r.column(ReleaseDetails::getStage);
                });
//                .include(r -> r.one(ReleaseDetails::getTask))
//                .toPageResult(page.getPageNum(), page.getPageSize());
        var rst=queryHelper.queryable(ReleaseDetails.class)
                .rightJoin(query,(p1,p2)->p1.eq(p2,ReleaseDetails::getId,ReleaseDetails::getId).eq(p2,ReleaseDetails::getReleaseTaskId,ReleaseDetails::getReleaseTaskId).eq(p2,ReleaseDetails::getStage,ReleaseDetails::getStage))
                .whereObject(entity)
                .orderByObject(page)
                .include(r -> r.one(ReleaseDetails::getTask))
                .toPageResult(page.getPageNum(),page.getPageSize());
        return toTableDataInfoRows(rst);
    }

    @ApiOperation(value = "查询各阶段前几条",notes = "用于榜单大屏:待揭榜30、挂帅中50(攻榜中)、挂帅成功60、评榜61、奖榜62，用榜63")
    @GetMapping("/detailTopByStage")
    public R<List<DefaultKeyValue<Integer, List<ReleaseDetails>>>> detailTopByStage(ReleaseDetails entity, Integer top) {
        //待揭榜30、挂帅中50(攻榜中)、挂帅成功60、评榜61、奖榜62，用榜63
        if (top == null || top < 1)
            top = 10;
        var list = queryHelper.query().queryable(sql + top, ReleaseDetails.class).whereObject(entity)
                .toList();//.include(r -> r.one(ReleaseDetails::getTask))
        var mainIds = list.stream().map(x -> x.getReleaseTaskId()).collect(Collectors.toList());
        var tasks = equeryable().whereByIds(mainIds).toList();
        list.forEach(p -> {
            var findRst = tasks.stream().filter(x -> Objects.equals(x.getId(), p.getReleaseTaskId())).findFirst();
            findRst.ifPresent(p::setTask);
        });
        var ret = new ArrayList<DefaultKeyValue<Integer, List<ReleaseDetails>>>();
        DefaultKeyValue<Integer, List<ReleaseDetails>> nowItems = null;
        ReleaseDetails tmpOld = null;
        for (var item : list) {
            if (tmpOld == null || !Objects.equals(item.getStage(), tmpOld.getStage())) {
                nowItems = new DefaultKeyValue<>();
                nowItems.setKey(item.getStage());
                nowItems.setValue(new ArrayList<>());
                ret.add(nowItems);
            }
            nowItems.getValue().add(item);
            tmpOld = item;
        }
        var re40 = ret.stream().filter(p -> p.getKey() == 40).findFirst();
        var re50 = ret.stream().filter(p -> p.getKey() == 50).findFirst();
        if (re50.isPresent()) {
            var p = re50.get();
            var finalTop = top.longValue();
            re40.ifPresent(x -> {
                var list50 = p.getValue();
                list50.addAll(x.getValue());
                list50.sort((y, y1) -> -y.getCreateTime().compareTo(y1.getCreateTime()));
                list50 = list50.stream().limit(finalTop).collect(Collectors.toList());
                p.setValue(list50);
                ret.remove(x);
            });
        } else
            re40.ifPresent(p -> {
                re40.get().setKey(50);
            });

        return R.ok(ret);
    }
    String sql="SELECT * FROM ( SELECT *, @row_num := IF(@current_type = stage, @row_num + 1, 1) AS rn, @current_type := stage FROM ( select a.* from pb_release_details a RIGHT JOIN (select release_task_id,max(stage) stage from pb_release_details where stage in(30,40,60,61,62,63) GROUP BY release_task_id) b on a.release_task_id=b.release_task_id and a.stage=b.stage ) _sq_n1 ORDER BY stage, create_time DESC ) AS _sq_t WHERE rn <=";
    /**
     * 获详细信息
     */
    @ApiOperation(value = "详情",notes = ConstData.ReleaseTask_StageVals)
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.list)")
    @GetMapping(value = "/{id}")
    public R<ReleaseTask> getInfo(@PathVariable("id") Long id) {
        var re = equeryable().include(r -> r.many(ReleaseTask::getChilds)).whereById(id).firstOrNull();
        re.getChilds().sort((p,p1)->-p.getCreateTime().compareTo(p1.getCreateTime()));
        return R.ok(re);
    }

    /**
     * 新增 阶段：0草稿，1申请中(寻榜)、20审批通过(定榜)、21审批驳回、30发榜、40揭榜、50攻榜、60完成、61评榜、62奖榜、63用榜
     */
    @ApiOperation(value = "申请", notes = "必须参数：stage、title、content")
    @PreAuthorize("@ss.hasAnyPermi(@pb.releaseTask.applyFor+','+@pb.releaseTask.myList)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.INSERT)
    @PostMapping("/applyFor")
    public R applyFor(@RequestBody ReleaseTaskDto entity) {
        if (StringUtils.isBlank(entity.getTitle()))
            return R.bad("标题不能为空");
        if (entity.getStage() != 0 && entity.getStage() != 1)
            return R.bad("阶段只能是草稿或提交申请");
        var rt = new ReleaseTask();
        rt.setTitle(entity.getTitle());
        rt.setContent(entity.getContent());
        rt.setStage(entity.getStage());
        rt.setFiles(entity.getFiles());
        rt.setOriginator(getLoginUser().getUser().getNickName());
        rt.setCreateBy(getUsername());
        rt.setCreateTime(new Date());
        super.add(rt);
        if (rt.getStage() == ReleaseTask.StageVal.申请中) {
            var rd = createDetail(rt);
            rd.setTitle("提交");
            queryHelper.query().insertable(rd).executeRows();
        }
        return R.ok();
    }

    @ApiOperation("提交")
    @PreAuthorize("@ss.hasAnyPermi(@pb.releaseTask.submit+','+@pb.releaseTask.myList)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/submit")
    public R<Long> submit(@RequestBody ReleaseTaskDto entity) {
        var rt = equeryable().whereById(entity.getId()).firstOrNull();
        if (rt.getStage() != ReleaseTask.StageVal.草稿)
            return R.bad("不是草稿状态");
        rt.setStage(1);
        rt.setUpdateBy(getUsername());
        rt.setUpdateTime(new Date());
        var rd = createDetail(rt);
        rd.setTitle("提交");
        rd.setFiles(rt.getFiles());
        var re = super.edit(rt);
        queryHelper.query().insertable(rd).executeRows();
        return re;
    }

    private ReleaseDetails createDetail(ReleaseTask rt) {
        var rd = new ReleaseDetails();
        rd.setReleaseTaskId(rt.getId());
        rd.setStage(rt.getStage());
        rd.setTitle(rt.getTitle());
        rd.setContent(rt.getTitle());
        rd.setNikename(getLoginUser().getUser().getNickName());
        rd.setCreateBy(getUsername());
        rd.setCreateTime(new Date());
        return rd;
    }

    boolean inList(Object source, Object... vals) {
        return Arrays.stream(vals).anyMatch(p -> Objects.equals(source, p));
    }

    R<ReleaseTask> selectOld(IEQueryEntity<Long> entity, Object... stages) {
        var re = equeryable().whereById(entity.getId()).firstOrNull();
        if (re == null || !inList(re.getStage(), stages))
            return R.bad("请检查数据id及所属阶段是否正确");
        return R.ok(re);
    }

    @ApiOperation("审批")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.approval)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/approval")
    public R approval(@RequestBody ReleaseTaskDto entity) {
        if (!inList(entity.getStage(), ReleaseTask.StageVal.审批通过, ReleaseTask.StageVal.审批驳回))
            return R.bad("阶段状态必须为：审批通过或审批驳回");
        var re = selectOld(entity, ReleaseTask.StageVal.申请中);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setStage(entity.getStage());
        rt.setRecord(entity.getRecord());
        rt.setApprove(getLoginUser().getUser().getNickName());
        super.edit(rt);
        var rd = createDetail(rt);
        rd.setContent(rt.getRecord());
        rd.setFiles(entity.getFiles());
        rd.setTitle(rt.getStage() == ReleaseTask.StageVal.审批通过 ? "审批通过" : "审批驳回");
        queryHelper.query().insertable(rd).executeRows();
        return R.ok();
    }
    @ApiOperation("发榜")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.publish)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/publish")
    public R publish(@RequestBody ReleaseTaskDto entity) {
        var re = selectOld(entity, ReleaseTask.StageVal.审批通过);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setStage(ReleaseTask.StageVal.发榜);
        rt.setUpdateBy(getUsername());
        rt.setUpdateTime(new Date());
        var rd = createDetail(rt);
        rd.setTitle("发榜");
        rd.setFiles(entity.getFiles());
        super.edit(rt);
        queryHelper.query().insertable(rd).executeRows();
        return re;
    }


    @ApiOperation("揭榜")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.acceptTask)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/acceptTask")
    public R acceptTask(@RequestBody ReleaseTaskDto entity) {
        var re = selectOld(entity, ReleaseTask.StageVal.发榜);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setImplementer(getLoginUser().getUser().getNickName());
        rt.setImplementerId(getUserId());
        rt.setUpdateBy(getUsername());
        rt.setUpdateTime(new Date());
        rt.setStage(ReleaseTask.StageVal.攻榜);
        var rd = createDetail(rt);
        rd.setStage(ReleaseTask.StageVal.揭榜);
        rd.setTitle("揭榜");
        rd.setFiles(entity.getFiles());
        queryHelper.query().insertable(rd).executeRows();
        return super.edit(rt);
    }
    @Resource
    PermissionService permissionService;
    @ApiOperation(value = "揭榜列表",notes ="如果无完成权限则只显示我的揭榜")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.records)")
    @GetMapping("/records")
    public TableDataInfoRows<ReleaseTask> records(ReleaseTask entity, PageSort page) {
        if (!permissionService.hasPermi(PbPower.releaseTask.done)) {
            entity.setImplementerId(getUserId());   //只能看自己的攻榜记录
        }
        var re = super.list(entity, page);
        return re;
    }

    @ApiOperation("攻榜记录添加")
    @PreAuthorize("@ss.hasAnyPermi(@pb.releaseTask.addRecord+','+@pb.releaseTask.records)")
    @Log(title = "揭榜挂帅详情", businessType = BusinessType.INSERT)
    @PostMapping("/addRecord")
    public R addRecord(@RequestBody ReleaseTaskDto entity) {
        var re = selectOld(entity, ReleaseTask.StageVal.攻榜);
        if (!re.isSuccess())
            return re;

        var rt = re.getData();
        if(!Objects.equals(rt.getImplementerId(), getUserId()))
            return R.bad("非揭榜人不能添加攻榜记录");
        var rd = createDetail(rt);
        rd.setTitle(entity.getTitle());
        rd.setContent(entity.getContent());
        rd.setFiles(entity.getFiles());
        queryHelper.query().insertable(rd).executeRows();
        return R.ok();
    }

    @ApiOperation(value = "完成",notes = "id,content")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.done)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/done")
    public R done(@RequestBody ReleaseTaskDto entity) {
        var re = selectOld(entity, ReleaseTask.StageVal.攻榜);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setStage(ReleaseTask.StageVal.完成);
        //rt.setRating(entity.getRating());
        rt.setUpdateBy(getUsername());
        rt.setUpdateTime(new Date());
        var rd = createDetail(rt);
        rd.setTitle("完成榜单");
        rd.setContent(entity.getContent());
        rd.setFiles(entity.getFiles());
        queryHelper.query().insertable(rd).executeRows();
        return super.edit(rt);
    }

    @ApiOperation("评价")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.review)")
    @Log(title = "揭榜挂帅详情", businessType = BusinessType.INSERT)
    @PostMapping("/review")
    public R review(@RequestBody ReleaseTaskDto entity) {
        entity.setTitle("评价");
        return afterDoneAppend(entity, ReleaseTask.StageVal.评榜);
    }

    private R<?> afterDoneAppend(ReleaseTaskDto entity, int stage) {
        var re = selectOld(entity, ReleaseTask.StageVal.完成);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setStageExt(stageExtSet(stage, rt.getStageExt()));
        if (entity.getRating() != null && stage == ReleaseTask.StageVal.评榜)
        {
            rt.setRating(entity.getRating());
            rt.setReviewers(getLoginUser().getUser().getNickName());
        }
        var rd = createDetail(rt);
        rd.setStage(stage);
        rd.setTitle(entity.getTitle()+"");
        rd.setContent(entity.getContent());
        rd.setFiles(entity.getFiles());
        edit(rt);
        queryHelper.query().insertable(rd).executeRows();
        return R.ok();
    }

    private static String stageExtSet(int stage, String oldExt) {
        if (StringUtils.isBlank(oldExt)) {
            return (stage - 60) + "";
        }
        var cnt = oldExt.contains((stage - 60) + "");
        if (cnt)
            throw ClientTipsException.bad("已存在此类型的追加信息:" + stage);
        var arr = (oldExt + (stage - 60)).toCharArray();
        Arrays.sort(arr);
        return String.copyValueOf(arr);
    }

    @ApiOperation("奖励")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.reward)")
    @Log(title = "揭榜挂帅详情", businessType = BusinessType.INSERT)
    @PostMapping("/reward")
    public R reward(@RequestBody ReleaseTaskDto entity) {

        return afterDoneAppend(entity, ReleaseTask.StageVal.奖榜);
    }

    @ApiOperation("用榜")
    @PreAuthorize("@ss.hasPermi(@pb.releaseTask.usage)")
    @Log(title = "揭榜挂帅详情", businessType = BusinessType.INSERT)
    @PostMapping("/usage")
    public R usage(@RequestBody ReleaseTaskDto entity) {
        return afterDoneAppend(entity, ReleaseTask.StageVal.用榜);
    }

    /**
     * 修改
     */
    @ApiOperation("草稿编辑")
    @PreAuthorize("@ss.hasAnyPermi(@pb.releaseTask.edit+','+@pb.releaseTask.myList)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @DataScope
    public R edit(@RequestBody ReleaseTaskDto entity) {
        var re = selectOld(entity, ReleaseTask.StageVal.草稿);
        if (!re.isSuccess())
            return re;
        var rt = re.getData();
        rt.setTitle(entity.getTitle());
        rt.setContent(entity.getContent());
        rt.setUpdateBy(getUsername());
        rt.setUpdateTime(new Date());
        rt.setFiles(entity.getFiles());
        return super.edit(rt);
    }


    /**
     * 删除
     */
    @ApiOperation("删除草稿")
    @PreAuthorize("@ss.hasAnyPermi(@pb.releaseTask.remove+','+@pb.releaseTask.myList)")
    @Log(title = "揭榜挂帅", businessType = BusinessType.DELETE)
    @PostMapping("remove/{id}")
    public R remove(@PathVariable Long id) {
        var entity = new ReleaseTask();
        entity.setId(id);
        var re = selectOld(entity, ReleaseTask.StageVal.草稿);
        if (!re.isSuccess())
            return re;
        return super.remove(new Object[]{id});
    }
}
